package com.sw.render.png;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import com.sw.model.Point;
import com.sw.render.TileRender;
import com.tilemr.map.MapUtil;
import com.tilemr.render.RenderUtil;
import com.tilemr.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PngTileRender implements TileRender {
    private static final Logger LOG = LoggerFactory.getLogger(PngTileRender.class);

    private String tilesPath = "D:\\tiles";
    private ColorSet mapColor = new ColorSet();

    public PngTileRender() {
    }

    @Override
    public void renderTile(Point point, String path) {
        int zoom = 13;
        int level = 5;
        double lat = point.getX();
        double lon = point.getY();
        String user = point.getUser();
        for (String type : point.getValues().keySet()) {
            double value = point.getValues().get(type);
            for (int z = zoom; z <= zoom + 5; z++) {
                String subtilePath = MapUtil.getSubtilePath(lat, lon, z, level);
                String tile = MapUtil.getTile(lat, lon, z);
                String tileArea = RenderUtil.findImageArea(subtilePath);
                // System.out.println("z,area,tile,subtile, : " + z + "," +
                // tileArea
                // + "," + tile + "," + subtilePath);
                try {
                    drawTileArea(tile, tileArea, user, type, value, null, path);
                } catch (Exception e) {
                    System.out.println("Exception2 EagleServlet.doPost(,)" + e);
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void renderTile(Point point, OutputStream stream) {
        LOG.debug("Rendering point=[" + point.toString() + "}");
        int zoom = 13;
        int level = 5;
        double lat = point.getX();
        double lon = point.getY();
        String user = point.getUser();
        for (String type : point.getValues().keySet()) {
            double value = point.getValues().get(type);
            for (int z = zoom; z <= zoom + 5; z++) {
                String subtilePath = MapUtil.getSubtilePath(lat, lon, z, level);
                String tile = MapUtil.getTile(lat, lon, z);
                String tileArea = RenderUtil.findImageArea(subtilePath);
                // System.out.println("z,area,tile,subtile, : " + z + "," +
                // tileArea
                // + "," + tile + "," + subtilePath);
                try {
                    drawTileArea(tile, tileArea, user, type, value, stream, tilesPath);
                } catch (Exception e) {
                    System.out.println("Exception2 EagleServlet.doPost(,)" + e);
                    e.printStackTrace();
                }
            }
        }
    }

    private void drawTileArea(String tile, String tileArea, String user,
                              String type, double value, OutputStream stream, String realPath) throws IOException {
        int width = 256;
        int height = 256;
        BufferedImage image = null;
        String path = realPath +"/"+ user + "/" + type + "/" + tile + ".png";
        File file = new File(path);
        if (file.exists()) {
            image = ImageIO.read(file);
        } else {
            File directory = new File(file.getParent());
            directory.mkdirs();
            image = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_ARGB);
        }
        Graphics g = image.getGraphics();
        String[] splitA = tileArea.split("\\" + Constants.TILE_PATH_DELIM);
        int minValue = mapColor.getMinValues().get(type);
        int maxValue = mapColor.getMaxValues().get(type);
        double waveLength = getWaveLength(value, minValue, maxValue);
        Color c = mapColor.getColors().get(type).selectColor((int) waveLength);
        g.setColor(c);
        int xSize = Integer.valueOf(splitA[0]);
        int ySize = Integer.valueOf(splitA[1]);
        int size = Integer.valueOf(splitA[2]);
        // g.fillRect(xSize, ySize, size, size);
        g.fillOval(xSize, ySize, size + 5, size + 5);
        System.out.println("drawing file : " + file);
        if (stream != null) {
            ImageIO.write(image, "PNG", stream);
        } else {
            ImageIO.write(image, "PNG", file);
        }
    }


    private double getWaveLength(double value, long minValue, long maxValue) {
        // Convert data value in the range of minValues...maxValues
        double minVisibleWaveLength = 0.0;
        double maxVisibleWaveLength = 240.0;
        double result = (double) (value - minValue) / (maxValue - minValue)
                * (maxVisibleWaveLength - minVisibleWaveLength)
                + minVisibleWaveLength;
        return result <= 240 ? result : 240;
    }

}
